#!/usr/bin/python
from __future__ import print_function
from subprocess import check_output
from sys import argv
import re

# Inspired by Rockbox version.sh

# Return False if files exactly match git commit at HEAD, True otherwise
def git_modified(path):
    try:
        s = check_output(['git', 'status', '--porcelain'],
                           universal_newlines=True, cwd=path)

        for line in s.splitlines():
            if len(line) > 3 and not line.startswith('?? '):
                return True
        return False
    except:
        return False

# Return short git hash for commit at HEAD
def git_rev(path):
    try:
        rev = check_output(['git', 'rev-parse', \
                           '--verify', '--short', 'HEAD'], \
                           universal_newlines=True, cwd=path).splitlines()[0]
    except:
        rev = 'UNKNOWN'

    return rev

# Find SVN revision corresponding to particular git commit
# This doesn't depend on git-svn, because it reads the log message instead.
def svn_rev(path, rev):
    try:
        commit_msg = check_output(['git', 'log',  '--format=%B', '-n',  '1',
                                   rev], universal_newlines=True, cwd=path)
        for l in commit_msg.splitlines():
            if l.startswith('git-svn-id:'):
                 m = re.match('^git-svn-id: .*/dosbox/trunk@([0-9]+) ', l)
                 return 'r' + m.group(1)
    except:
        return ''

# Find git commit corresponding to SVN revision from where HEAD diverges
def svn_base(path, rev):
    try:
        merge_base = check_output(['git', 'merge-base', 'master', rev],
                                  universal_newlines=True, cwd=path).rstrip()
        return svn_rev(path, merge_base)
    except:
        return ''

# This tries to construct a compiler version string.
# Ideally having the configure options and compiler flags would be nice.
def compiler_rev(compiler):
    try:
        out = check_output(compiler + ['--version'],
                           universal_newlines=True).splitlines()[0]

        if out.startswith('em'):
            # Assume emscripten
            m = re.match('^[^)]+\) ([^ ]+) \((?:commit )?(.......).*$', out)
            rev = 'Emscripten ' + m.group(1) + ' ' + m.group(2)
        else:
            m = re.match('^([^ ]+) .* ([^ ]+)$', out)
            # Assume something like GCC
            rev = m.group(1) + ' ' + m.group(2)
    except:
        rev = 'UNKNOWN'

    return rev;

def make_version_h(gitpath, compiler):
    gitr = git_rev(gitpath)
    if gitr != 'UNKNOWN':
        svnr = svn_base(gitpath, gitr)
        if svnr != '':
            svnr += '+'
        if git_modified(gitpath):
            gitr += 'M'
    else:
        svnr = ''

    return '/* Version info file automatically generated by version.py */\n' + \
           '#define VERSION_TEXT "' + svnr + gitr + \
           ' built with ' + compiler_rev(compiler) + '"\n';

# Program begins here

if len(argv) < 4:
    print("Usage: python", argv[0],
          "VERSION_HEADER GIT_PATH COMPILER_EXECUTABLE [ARGUMENTS...]")
    exit(1)

current_version = make_version_h(argv[2], argv[3:])

# Only update file if version info has changed

try:
    with open(argv[1], 'r') as f:
        old_version = f.read()
except:
    old_version = ''

if old_version != current_version:
    with open(argv[1], 'w') as f:
        f.write(current_version)
